--[[
pata副本相关逻辑
接口列表：

--]]
local Lang = require("common.Lang")
local PataExcel = require("excel.Pata")
local Timer = require("core.Timer")
local ObjHuman = require("core.ObjHuman")
local Msg = require("core.Msg")
local ItemDefine = require("bag.ItemDefine")
local BagLogic = require("bag.BagLogic")
local Copy = require("copy.CopyL")
local CopyHandler = require("copy.HandlerL")
local CopyDefine = require("copy.Define")
local Broadcast = require("broadcast.Broadcast")
local ShopHelp = require("shop.ShopHelp")
local VipLogic = require("vip.VipLogic")
local VipDefine = require("vip.VipDefine")
local MonthCardLogic = require("vip.MonthCardLogic")
local Aim = require("copy.Aim")
local Grid = require("bag.Grid")
local DropLogic = require("monster.DropLogic")
local ObjItem = require("core.ObjItem")
local Map = require("core.Map")
local PataCopyID = {408}
local RankDefine = require("rank.RankDefine")
local Log = require("common.Log")
local ExpLogic = require("monster.ExpLogic")
local TaskCallbacks = require("task.TaskCallbacks")
local Obj = require("core.Obj")
local SceneEvent = require("core.SceneEvent")
local OfficialLogic = require("official.OfficialLogic")

FIRST_DIE_GIFT_ITEM_ID = 12138					-- 爬塔首次死亡鼓励礼包
FIRST_DIE_GIFT_ITEM_CACHE = FIRST_DIE_GIFT_ITEM_CACHE or nil --爬塔首次死亡鼓励礼包grid缓存

PataData = PataData or {}

function isPataCopy(copyID)
    for _, v in pairs(PataCopyID) do
        if v == copyID then
            return true
        end
    end
end
function getMaxCnt(human)
    return CopyDefine.PATA_FREE_RESET_CNT+ human.db.pata_add
end

SHOW_REWARD_CACHE = nil
function makeShowReward(human, info)
    if SHOW_REWARD_CACHE == nil then
        SHOW_REWARD_CACHE = {}
        for i = 1, #PataExcel.showReward[1].reward do
            SHOW_REWARD_CACHE[i] = {}
            Grid.create(SHOW_REWARD_CACHE[i], PataExcel.showReward[1].reward[i][1], PataExcel.showReward[1].reward[i][2], PataExcel.showReward[1].reward[i][3], PataExcel.showReward[1].reward[i][4])
            if i == 10 then
                break
            end
        end
    end

    for i = 1, #SHOW_REWARD_CACHE do
        Grid.makeItem( SHOW_REWARD_CACHE[i], info[i], 0, human)
    end
    info[0] = #SHOW_REWARD_CACHE
end
function makeShowRewardPerGuan(human, config, info)
    if config.showGrids == nil then
        config.showGrids = {}
        for i = 1, #config.showReward do
            config.showGrids[i] = {}
            Grid.create(config.showGrids[i], config.showReward[i][1], config.showReward[i][2], config.showReward[i][3], config.showReward[i][4])
            if i == 6 then
                break
            end
        end
    end

    for i = 1, #config.showGrids do
        Grid.makeItem( config.showGrids[i], info[i], 0, human)
    end
    info[0] = #config.showGrids
end

function makeShowFirstReward(human, config, info)
    info.firstreward[0] = 0
    info.hasreward = 0
    local nCurFloorIndex = human.db.pata_cur

    local nFirstConfig = nil
    for i = 1, #(PataExcel.pata_first) do
        if PataExcel.pata_first[i].pataid == nCurFloorIndex then
            if human.db.pata_first[i - 1] == 1 then
                info.hasreward = 1
                break
            end
            nFirstConfig = PataExcel.pata_first[i]
            if nFirstConfig.grid == nil then
                nFirstConfig.grid = {}
                Grid.create(nFirstConfig.grid, nFirstConfig.reward, 1)
            end
            break
        end
    end

    if nFirstConfig and nFirstConfig.grid then
        Grid.makeItem(nFirstConfig.grid, info.firstreward[1], 0, human)
        info.firstreward[0] = 1 
    end
end

function query(human, sendReward)
    local msgRet = Msg.gc.GC_COPY_PATA_QUERY
    msgRet.sendReward = sendReward == 0 and 0 or 1
    msgRet.curIndex = human.db.pata_cur
    msgRet.maxIndex = human.db.pata_max
    msgRet.curResetCnt = human.db.pata_reset
    msgRet.totalIndex  = #(PataExcel.pata)
    msgRet.maxResetCnt = getMaxCnt(human)
    msgRet.addResetCnt = VipLogic.getVipTimes(human, VipDefine.VIP_PRIVILEGE_PATACOPY) - human.db.pata_add
    msgRet.addResetCnt = msgRet.addResetCnt>0 and msgRet.addResetCnt or 0
    local config = PataExcel.pata[human.db.pata_max+1]
    msgRet.zhandouli   =  config and config.zhandouli or 0
    msgRet.koCnt = human.db.pata_ko
    msgRet.koMaxCnt = 1
    msgRet.koYuanbao = PataExcel.pata[human.db.pata_max] and PataExcel.pata[human.db.pata_max].koYuanbao or 0
    if sendReward == 0 then
        msgRet.items[0] = 0
    else
        makeShowReward(human, msgRet.items)
    end
    Msg.send(msgRet, human.fd)
end

function query_first(human)  --道通奖励查询
    local msgRet = Msg.gc.GC_COPY_PATA_FIRST_QUERY
    local len = 0
    for i = 1, #(PataExcel.pata_first) do
        len = len + 1
        local v = PataExcel.pata_first[i]
        if v.grid == nil then
            v.grid = {}
            Grid.create(v.grid, v.reward, 1, true)
        end
        Grid.makeItem(v.grid, msgRet.first[len].reward, 0, human)
        msgRet.first[len].guan = v.pataid
        if v.pataid > human.db.pata_max then
            msgRet.first[len].status = 2
        elseif human.db.pata_first[i-1] == 1 then
            msgRet.first[len].status = 0
        else
            msgRet.first[len].status = 1
        end
    end
    msgRet.first[0] = len
    Msg.send(msgRet, human.fd)
end

function first_get(human, guan) -- 得到首通奖励
    local config
    local ok
    for i = 1, #(PataExcel.pata_first) do
        config = PataExcel.pata_first[i]
        if config.pataid == guan then
            ok = i
            break
        end
    end
    if ok == nil then
        return
    end
    if config.pataid > human.db.pata_max then
        return
    end
    if human.db.pata_first[ok-1] == 1 then
        return
    end
    if not config.grid then
        config.grid = {}
        Grid.create(config.grid, config.reward, 1, true)
    end
    if not BagLogic.checkCanAddItem(human, config.grid.id, config.grid.bind, config.grid.cnt, config.grid.lifeTime) then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.SHOP_ERR_BAG_FULL)
        return
    end
    BagLogic.addItem(human, config.grid.id, config.grid.bind, config.grid.cnt, "pata", nil, config.grid.lifeTime)
    Broadcast.sendBroadcast(human,  Lang.MOUSE, string.format(Lang.COPY_PATA_GETFIRST_OK, config.pataid))
    human.db.pata_first[ok-1] = 1
    query_first(human)
end

function copyEnter(human, noCheckCopy)
    if human.scene_id == nil then
        return
    end
    if human.db.pata_cur == 0 then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_ENTER_FAIL)
        return
    end
    local config = PataExcel.pata[human.db.pata_cur]
    CopyHandler.copyEnter(human, config.copyID, noCheckCopy)
    Log.write(Log.LOGID_OSS_PATA_COPY, human._id, human.account, human.name, human.db.lv, 1, human.db.pata_max)
end


function reset(human)
    if human.db.pata_reset >= getMaxCnt(human) then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_RESET_FAIL)
        return
    end
    human.db.pata_reset  = human.db.pata_reset + 1
    human.db.pata_cur = 1
    human.db.pata_ko = 0
    query(human, 0)
    Log.write(Log.LOGID_OSS_PATA_COPY, human._id, human.account, human.name, human.db.lv, 2, human.db.pata_max)
end

function add_reset(human)  --增加重置次数
    local cnt = VipLogic.getVipTimes(human, VipDefine.VIP_PRIVILEGE_PATACOPY)
    if cnt == 0 then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.TASK_ADD_CNT_NOT_VIP)
        return
    end
    if human.db.pata_add >= cnt then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_ADD_FULL)
        return
    end
    if ObjHuman.getYuanbao(human) < CopyDefine.PATA_ADD_RESET_YUANBAO then
        ShopHelp.onNoRMB(human)
        return
    end
    ObjHuman.decYuanbao(human, CopyDefine.PATA_ADD_RESET_YUANBAO, "pata")
    human.db.pata_add = human.db.pata_add + 1
    query(human, 0)
    Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_ADD_OK)
end

--扫荡奖励
function create_ko_reward(human, pata_max)
    local rewardGrid = {}
    for i = 1, pata_max do
        local config = PataExcel.pata[i]
        if config.bossID >0 then
            local len, list = DropLogic.getMonsterDropGrids(human, config.bossID)
            for j=1, len do
                BagLogic.addItemToArray(rewardGrid,  list[j])
            end
        end
    end
    local r = VipLogic.getVipTimes(human, VipDefine.VIP_PRIVILEGE_PATA_REWARD)
    if r>1 then -- 至尊会号 +20%
        for i = 1, #rewardGrid do
            if ItemDefine.is_spobj[rewardGrid[i].id] then
                rewardGrid[i].cnt = math.ceil(rewardGrid[i].cnt*r)
            elseif ItemDefine.canAppend(rewardGrid[i].id) then
                rewardGrid[i].cnt = math.ceil(rewardGrid[i].cnt*r)
            end
        end
    end
    return rewardGrid
end

--扫荡经验
function create_ko_exp(human, pata_max)
    local exp = 0
    for i = 1, pata_max do
        local config = PataExcel.pata[i]
        if config.bossID >0 then
            exp = exp + ExpLogic.getSingleExp(human, config.bossID)
        end
    end
    local r = VipLogic.getVipTimes(human, VipDefine.VIP_PRIVILEGE_PATA_REWARD)
    if r > 1 then
        exp = exp*r
    end
    return math.floor(exp)
end

--扫荡
function ko(human)
    if human.db.pata_cur ~= 1 then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_KO_FROM_1)
        return
    end
    if human.db.pata_ko == 1 then
        return
    end
    if not MonthCardLogic.isHaveSpec(human) then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_KO_NO_VIP)
        return
    end
    local config = PataExcel.pata[human.db.pata_max]
    
    if ObjHuman.getYuanbao(human) <  config.koYuanbao then
        ShopHelp.onNoRMB(human)
        return
    end
    ObjHuman.decYuanbao(human, config.koYuanbao, "pata")
    local rewardGrid = create_ko_reward(human, human.db.pata_max)

    local msg = Msg.gc.GC_COPY_PATA_KO
    msg.reward[0] = 0
    local len = 0
    for i = 1, #rewardGrid do
        len = len + 1
        Grid.makeItem(rewardGrid[i], msg.reward[len], 0, human)
        if len == 18 then
            break
        end
    end
    msg.reward[0] = len
    Msg.send(msg, human.fd)

    local exp = create_ko_exp(human, human.db.pata_max)
    if exp > 0 then
        ObjHuman.addExp(human, exp)
    end

    human.pata_ko_reward = rewardGrid
    human.db.pata_ko_reward = human.db.pata_max
    human.db.pata_ko = 1

    human.db.pata_cur = human.db.pata_max + 1
    if human.db.pata_cur > #(PataExcel.pata) then
        human.db.pata_cur = 0
    end
    Log.write(Log.LOGID_OSS_PATA_COPY, human._id, human.account, human.name, human.db.lv, 3, human.db.pata_max)
    query(human, 0)
end

--添加奖励到斩将宝箱
local function addRewardToStore(human, grid)
    if BagLogic.checkCanAddItem2(human.db.pata_store, human.db.pata_storeLen, grid.id, grid.bind, grid.cnt, grid.lifeTime) then
        if ItemDefine.isEquip(grid.id) then  -- 背包满，放到斩将宝库
            for i = 0, human.db.pata_storeLen - 1 do
                local empty = human.db.pata_store[i]
                if empty.id == 0 then
                    Grid.copy(empty, grid)
                    grid.id = 0
                    break
                end
            end
        else
            BagLogic.addItem2(human.db.pata_store, human.db.pata_storeLen, grid.id, grid.bind, grid.cnt, nil, grid.lifeTime)
        end
        return true
    end
end
function ko_reward(human, type)
    if human.pata_ko_reward  == nil  and human.db.pata_ko_reward == 0 then
        return
    end
    if human.pata_ko_reward == nil then
        human.pata_ko_reward = create_ko_reward(human, human.db.pata_ko_reward)
    end
    local store
    if type == 1 then
        for i = 1, #human.pata_ko_reward do
            local grid = human.pata_ko_reward[i]
            if BagLogic.checkCanAddItem(human, grid.id, grid.bind, grid.cnt, grid.lifeTime) then
                if ItemDefine.isEquip(grid.id) then --放到背包
                    BagLogic.addItemByGrid(human, nil, grid, "pata")
                else
                    BagLogic.addItem(human, grid.id, grid.bind, grid.cnt, "pata", nil, grid.lifeTime)
                end
            elseif addRewardToStore(human, grid) then
                store = true
            end
        end
    else
        for i = 1, #human.pata_ko_reward do
            local grid = human.pata_ko_reward[i]
            if addRewardToStore(human, grid) then
                store = true
            end
        end
    end
    human.pata_ko_reward = nil
    human.db.pata_ko_reward = 0
    local msg = Msg.gc.GC_COPY_PATA_KO_GET
    msg.result = 0
    Msg.send(msg, human.fd)
    if store then
        Broadcast.sendBroadcast(human,  Lang.DOWN, Lang.COPY_PATA_KO_TO_STORE)
        sendStore(human)
    end
end

--拾取道具时，如果背包满了，直接放斩将宝箱
function pickUpWhenBagFull(human, grid)
    local copyid = Copy.isCopyBySceneID(human.scene_id)
    if not copyid then
        return
    end
    if not isPataCopy(copyid) then
        return
    end
    return addRewardToStore(human, grid)
end


--发送斩将宝库
function sendStore(human)
    Grid.makeList(human, human.db.pata_store, human.db.pata_storeLen, Msg.gc.GC_COPY_PATA_STORE)
end
-- 全部领取
local itemList = {}
function getAllStore(human)
    local len = 0
    for i = 0, human.db.pata_storeLen - 1 do
        if human.db.pata_store[i].id ~= 0 then
            len = len + 1
            itemList[len] = itemList[len] or {}
            itemList[len][1] = human.db.pata_store[i].id
            itemList[len][2]= human.db.pata_store[i].cnt
            itemList[len][3]= human.db.pata_store[i].bind
            itemList[len][4] = human.db.pata_store[i].lifeTime
            itemList[len][5] = nil
        end
    end
    if not BagLogic.checkCanAddItemList(human, itemList, len) then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.SHOP_ERR_BAG_FULL)
        return
    end
    for i = 0, human.db.pata_storeLen - 1 do
        local grid = human.db.pata_store[i]
        if grid.id ~= 0 then
            if ItemDefine.isEquip(grid.id) then
                BagLogic.addItemByGrid(human, nil, grid, "pata")
            else
                BagLogic.addItem(human, grid.id, grid.bind, grid.cnt, "pata", nil, grid.lifeTime)
            end
            grid.id = 0
        end
    end
    sendStore(human)
end

--领取一个
function getStore(human, pos)
    if pos < 0 or pos >=human.db.pata_storeLen then
        return
    end
    local grid = human.db.pata_store[pos]
    if grid.id == 0 or grid.cnt == 0 then
        return
    end
    if not BagLogic.checkCanAddItem(human, grid.id, grid.bind, grid.cnt, grid.lifeTime) then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.SHOP_ERR_BAG_FULL)
        return
    end
    if ItemDefine.isEquip(grid.id) then
        BagLogic.addItemByGrid(human, nil, grid, "pata")
    else
        BagLogic.addItem(human, grid.id, grid.bind, grid.cnt, "pata", nil, grid.lifeTime)
    end
end


function startPata(human, copyID, roomID)

    PataData[roomID] = PataData[roomID] or {}
    local config = PataExcel.pata[human.db.pata_cur]
    if PataData[roomID].pataID ~= human.db.pata_cur then
        PataData[roomID].pataID = human.db.pata_cur
        PataData[roomID].startTime = Timer.now
        PataData[roomID].aimID = config.copyAimID
        PataData[roomID].finish = nil
        PataData[roomID].bossDieTime = nil
        Aim.aimDoAccept(config.copyAimID, copyID, roomID)
    end

    ObjItem.clearOwnerItemByScene(human.scene_id)
    clearMonster(human.scene_id)
    local msgRet = Msg.gc.GC_COPY_PATA_ENTER
    msgRet.pataID = human.db.pata_cur
    msgRet.totalIndex  = #(PataExcel.pata)
    local config = PataExcel.pata[human.db.pata_cur]
    msgRet.desc = config.desc
    msgRet.nowSec = config.finishTime - (Timer.now - PataData[roomID].startTime)/1000
    makeShowRewardPerGuan(human, config, msgRet.reward)
    makeShowFirstReward(human, config, msgRet)
    Msg.send(msgRet, human.fd)
end

function clearMonster(scene_id)
    -- 爬塔每层结束的时候 把地上的无用的对象清一下
    if Obj.scenes[scene_id] then
        for _, v in pairs(Obj.scenes[scene_id]) do
            if v.obj_type == Obj.TYPE_AOE or v.obj_type == Obj.TYPE_SKILL or v.obj_type == Obj.TYPE_TRAP or (v.obj_type == Obj.TYPE_MONSTER and v.hp <= 0) then
                Obj.destroyAllType(v)
            end
        end
    end
end

function onPataHumanEnterCopyScene(human, copyID, roomID)--, sceneID)
    startPata(human, copyID, roomID)
    TaskCallbacks.taskPataCB(human, human.db.pata_max)
end


function onPataAimFinish(copyID, roomID)--, aimID)
    local humanList = Copy.getCopyHumanList(copyID, roomID)
    local human = humanList[1]
    if human == nil then return end
    if human.db.pata_cur == 0 then
        return
    end
    startPata(human, copyID, roomID)
end
function onPataOneSec(copyID, roomID)
    if PataData[roomID] == nil then return end
    local config = PataExcel.pata[PataData[roomID].pataID]
    if PataData[roomID].finish == nil and config.finishTime * 1000 + PataData[roomID].startTime <= Timer.now then
        -- 超时
        Copy.roomFinish(copyID, roomID, CopyDefine.COPY_FINISH_TIMEOUT, Lang.COPY_FINISH_TIMEOUT)
        return
    end

    if PataData[roomID].bossDieTime and Timer.now - PataData[roomID].bossDieTime >=2000 then
        PataData[roomID].bossDieTime = nil
        local humanList = Copy.getCopyHumanList(copyID, roomID)
        local human = humanList[1]
        if human == nil then return end
        local msg = Msg.gc.GC_COPY_PATA_JUMP_POS
        msg.pataID = PataData[roomID].pataID
        local list_rect = Map.getRects(Map.scene_id_to_map_id[human.scene_id], config.jumpArea)
        msg.x =  (list_rect[1][1] + list_rect[1][3]) / 2
        msg.y =  (list_rect[1][2] + list_rect[1][4]) / 2
        Msg.send(msg, human.fd)
    end
end

function onPataClear(copyID, roomID)
    PataData[roomID] = nil
end

function onPataRoomFinish(copyID, roomID, retCode) --先重置，防止在定时器重置前，怪物掉落
    local mapList = Copy.copyList[copyID][roomID]
    for mapID, sceneID in pairs(mapList) do
        if Obj.scenes[sceneID] then
            -- 重置地图事件
            SceneEvent.sceneClearExcepteHumanAndNpc(sceneID)
        end
    end
end

local hardCodeMonsterID = {[1004550] = 1, [1004551] =1, [1004552] = 1}
function onPataMonsterDie(killer, monster, monsterID, copyID, roomID)
    if PataData[roomID] == nil then return end
    local humanList = Copy.getCopyHumanList(copyID, roomID)
    local human = humanList[1]
    if human == nil then return end
    local config = PataExcel.pata[PataData[roomID].pataID]
    if not config then return  end
    if config.bossID == monsterID or hardCodeMonsterID[monsterID] then
        PataData[roomID].finish = true
    end
end

function ref_scene_event(sceneID)
    local copyID = Copy.sceneID2CopyID[sceneID]
    local roomID = Copy.sceneID2Room[sceneID]
    if copyID == nil or roomID == nil then return end
    if PataData[roomID] == nil then return end
    local humanList = Copy.getCopyHumanList(copyID, roomID)
    local human = humanList[1]
    if human == nil then return end
    if human.db.pata_cur > human.db.pata_max then
        human.db.pata_max = human.db.pata_cur
        --do some
        local sendMsg = Msg.lw.LW_CHECK_RANK_CHANGE
        sendMsg.type = RankDefine.PATA_RANK_TYPE
        sendMsg.otherInfo = 0
        Msg.send2world(sendMsg, human._id)
        OfficialLogic.checkOneCondition(human, "pataMax")
        TaskCallbacks.taskPataCB(human, human.db.pata_max)
    end
    human.db.pata_cur = human.db.pata_cur + 1
    if human.db.pata_cur > #(PataExcel.pata) then
        human.db.pata_cur = 0
    end
    PataData[roomID].finish = true
    PataData[roomID].bossDieTime = Timer.now
end

local function notifyFirstDie(human)
	if human.db.pata_first_die ~= 0 then return	end

	if FIRST_DIE_GIFT_ITEM_CACHE == nil or FIRST_DIE_GIFT_ITEM_CACHE.id ~= FIRST_DIE_GIFT_ITEM_ID then
		FIRST_DIE_GIFT_ITEM_CACHE = Grid.create(nil, FIRST_DIE_GIFT_ITEM_ID, 1, true)
	end
	
	local msgRet = Msg.gc.GC_COPY_PATA_FIRST_DIE_NOTIFY
	Grid.makeItem(FIRST_DIE_GIFT_ITEM_CACHE, msgRet.reward, 0, human)
	Msg.send(msgRet, human.fd)
end

function onPataRoleDie(atker, human, copyID, roomID)
	notifyFirstDie(human)
end

function firstDieGet(human)
	if human.db.pata_first_die ~= 0 then return	end
	
	if not BagLogic.checkCanAddItem(human, FIRST_DIE_GIFT_ITEM_ID, true, 1) then
        Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.SHOP_ERR_BAG_FULL)
        return
    end
    human.db.pata_first_die = 1
    BagLogic.addItem(human, FIRST_DIE_GIFT_ITEM_ID, true, 1, "pata")
    Broadcast.sendBroadcast(human,  Lang.MOUSE, Lang.COPY_PATA_FIRST_DIE_GIFT_GET)
end